package com.lsq.baseadmin.common.aspect;

import com.google.gson.Gson;
import com.lsq.baseadmin.common.utils.IpUtil;
import com.lsq.baseadmin.modules.manage.vo.UserVo;
import com.lsq.baseadmin.modules.manage.utils.AuthUtil;
import com.lsq.baseadmin.common.utils.MyUtil;
import com.lsq.baseadmin.common.utils.ThrowableUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author lsq
 * @date 2020年11月8日
 */
@Component
@Aspect
@Slf4j
public class LogAspect {

    private ThreadLocal<Long> currentTime = new ThreadLocal<>();

    @Pointcut("execution(public * com.lsq.baseadmin..*.controller..*(..))")
    public void webLog(){
    }

    @Around("webLog()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        currentTime.set(System.currentTimeMillis());
        Object o;
        StringBuilder sb = packLogInfo(joinPoint);
        boolean error = false;
        try {
            o = joinPoint.proceed();
            sb.append("返回内容: { ").append(new Gson().toJson(o)).append(" }");
        } catch (Exception e) {
            sb.append("返回内容（发生异常）: { ").append(ThrowableUtil.getStackTrace(e)).append(" }");
            error = true;
            throw e;
        } finally {
            sb.append("耗时: { ").append(String.valueOf(System.currentTimeMillis() - currentTime.get())).append(" } ");
            currentTime.remove();

            if(error) {
                log.error(sb.toString());
            } else {
                log.info(sb.toString());
            }
        }

        return o;
    }

    private StringBuilder packLogInfo(ProceedingJoinPoint joinPoint) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        StringBuilder sb = new StringBuilder();

        UserVo loginUser = AuthUtil.getLoginUser(request.getSession());
        if (null != loginUser) {
            sb.append("请求人: { ").append(loginUser.getUser().getLoginName()).append(": ").append(loginUser.getUser().getId()).append(" } ");
        }
        sb.append("地址: { ").append(request.getRequestURL().toString()).append(" } ");
        sb.append("类方法: { ").append(joinPoint.getSignature()).append(" } ");
        StringBuilder params = new StringBuilder();
        //参数值
        Object[] argValues = joinPoint.getArgs();
        //参数名称
        String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
        if(argValues != null){
            for (int i = 0; i < argValues.length; i++) {
                params.append(" ").append(argNames[i]).append(": ").append(argValues[i]);
            }
        }
        // Arrays.toString(joinPoint.getArgs())
        sb.append("类方法参数: { ").append(params.toString()).append(" } ");
        String ip = request.getRemoteAddr();
        sb.append("IP: { ").append(ip).append(" = ").append(IpUtil.getCityInfo(ip)).append(" } ");
        sb.append("浏览器: { ").append(MyUtil.getBrowser(request)).append(" } ");
        sb.append("方式: { ").append(request.getMethod()).append(" } ");

        return sb;
    }



}
